package com.ray.woodencreate.exception;

import com.ray.woodencreate.logs.SystemLogBuilder;
import com.ray.woodencreate.result.MsgCodeConstant;
import com.ray.woodencreate.result.MsgCodeUtil;
import com.ray.woodencreate.result.Result;
import com.ray.woodencreate.result.ResultFactory;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author bo shen
 * @Description: 统一异常处理
 * @Class: ExceptionHandle
 * @Package com.toptoday.woodencreate.exception
 * @date 2018/10/10 17:47
 * @company <p>Ray快速开发平台</p>
 * @updateRecord time(修改时间)  author(修改人)   desc(修改内容)
 */
@RestControllerAdvice
@Slf4j
public class ExceptionHandle {

    /**
     * 自动转换日期类型的字段格式
     */
    @InitBinder
    public void initBinder(ServletRequestDataBinder binder) {
        // 可以設定任意的日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        dateFormat.setLenient(false);
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
        binder.registerCustomEditor(String.class, new StringTrimmerEditor(false));
    }

    /**
     * @param exception  处理异常
     * @return
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result handle(MethodArgumentNotValidException exception) {

        BindingResult bindingResult = exception.getBindingResult();
        StringBuffer errorInfo = new StringBuffer();
        errorInfo.append(":");
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            errorInfo.append(fieldError.getDefaultMessage() + ", ");
        }
        String  errorCode = MsgCodeConstant.Error.ERR88000007;
        String msg = MsgCodeUtil.getMsgCodeMessage(errorCode) + errorInfo.toString();
        log.info(new SystemLogBuilder().appendLevelError(msg,getErrorClass(exception)).appendMsgCode(errorCode,errorInfo.toString()).bulidString());
        log.info("异常信息",exception);
        return ResultFactory.createErrorResult(errorCode,errorInfo.toString());
    }


    /**
     * @param exception  处理异常
     * @return
     */
    @ExceptionHandler(value = BusinessException.class)
    public Result handle(BusinessException exception) {
        String msg = null;
        //获取错误代码
        String errorCode = exception.getErrorCode();
        String[]  args = exception.getArgs();
        if(ObjectUtils.isEmpty(args)){
            msg = MsgCodeUtil.getMsgCodeMessage(errorCode);
        }else {
            msg = String.format(MsgCodeUtil.getMsgCodeMessage(errorCode),args);
        }
        log.info(new SystemLogBuilder().appendLevelError(msg,getErrorClass(exception)).appendMsgCode(errorCode,args).bulidString());
        log.info("异常信息",exception);
        return ResultFactory.createErrorResult(errorCode,args);
    }

    /**
     *
     * @param exception  处理异常
     * @return
     */
    @ExceptionHandler(value = ExpiredJwtException.class)
    public Result handle(ExpiredJwtException exception) {
        String[] args = null;
        String  errorCode = MsgCodeConstant.Error.ERR88000002;
        String msg = MsgCodeUtil.getMsgCodeMessage(errorCode);
        log.info(new SystemLogBuilder().appendLevelError(msg,getErrorClass(exception)).appendMsgCode(errorCode,args).bulidString());
        log.info("异常信息",exception);
        return ResultFactory.createErrorResult(errorCode,args);
    }


   /**
     *
     * @param exception  处理异常
     * @return
     */
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public Result handle(MissingServletRequestParameterException exception) {
        String[] args = null;
        String  errorCode = MsgCodeConstant.Error.ERR88000003;
        String msg = MsgCodeUtil.getMsgCodeMessage(errorCode);
        log.info(new SystemLogBuilder().appendLevelError(msg,getErrorClass(exception)).appendMsgCode(errorCode,args).bulidString());
        log.info("异常信息",exception);
        return ResultFactory.createErrorResult(errorCode,args);
    }

    /**
     *
     * @param exception  处理异常
     * @return
     */
    @ExceptionHandler(value = MethodArgumentTypeMismatchException.class)
    public Result handle(MethodArgumentTypeMismatchException exception) {
        String[] args = null;
        String  errorCode = MsgCodeConstant.Error.ERR88000004;
        String msg = MsgCodeUtil.getMsgCodeMessage(errorCode);
        log.info(new SystemLogBuilder().appendLevelError(msg,getErrorClass(exception)).appendMsgCode(errorCode,args).bulidString());
        log.info("异常信息",exception);
        return ResultFactory.createErrorResult(errorCode,args);
    }

    /**
     *
     * @param exception  处理异常
     * @return
     */
    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    public Result handle(HttpRequestMethodNotSupportedException exception) {
        String[] args = null;
        String  errorCode = MsgCodeConstant.Error.ERR88000005;
        String msg = MsgCodeUtil.getMsgCodeMessage(errorCode);
        log.info(new SystemLogBuilder().appendLevelError(msg,getErrorClass(exception)).appendMsgCode(errorCode,args).bulidString());
        log.info("异常信息",exception);
        return ResultFactory.createErrorResult(errorCode,args);
    }

    /**
     *
     * @param exception  处理异常
     * @return
     */
    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    public Result handle(HttpMessageNotReadableException exception) {
        String[] args = null;
        String  errorCode = MsgCodeConstant.Error.ERR88000006;
        String msg = MsgCodeUtil.getMsgCodeMessage(errorCode);
        log.info(new SystemLogBuilder().appendLevelError(msg,getErrorClass(exception)).appendMsgCode(errorCode,args).bulidString());
        log.info("异常信息",exception);
        return ResultFactory.createErrorResult(errorCode,args);
    }


    /**
     *
     * @param exception  处理异常
     * @return
     */
    @ExceptionHandler(value = IllegalArgumentException.class)
    public Result handle(IllegalArgumentException exception) {
        String[] args = null;
        String  errorCode = MsgCodeConstant.Error.ERR00000000;
        String  msg = exception.getClass().getName();
        log.info(new SystemLogBuilder().appendLevelError(exception.getMessage()).appendMsgCode(errorCode,args).bulidString());
        log.info(new SystemLogBuilder().appendLevelError(msg,getErrorClass(exception)).appendMsgCode(errorCode,args).bulidString());
        log.info("异常信息",exception);
        return ResultFactory.createErrorResult(errorCode,exception.getMessage());
    }
    /**
     *
     * @param exception  处理异常
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public Result handle(Exception exception) {
        String[] args = null;
        String  errorCode = MsgCodeConstant.Error.ERR00000001;
        String  msg = exception.getClass().getName();
        log.info(new SystemLogBuilder().appendLevelError(exception.getMessage()).appendMsgCode(errorCode,args).bulidString());
        log.info(new SystemLogBuilder().appendLevelError(msg,getErrorClass(exception)).appendMsgCode(errorCode,args).bulidString());
        log.info("异常信息",exception);
        return ResultFactory.createErrorResult(errorCode,args);
    }

    /**
     * 获取异常信息
     * @param exception
     * @return
     */
    private String getErrorClass(Exception exception) {
        StackTraceElement[] st = exception.getStackTrace();
        for (StackTraceElement stackTraceElement : st) {
            String exclass = stackTraceElement.getClassName();
            String method = stackTraceElement.getMethodName();
            return  exclass + "." + method;
        }
        return "";
    }

}
